package com.ihighest.app.common.api;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.InputStream;
import java.util.ArrayList;

import org.json.JSONArray;
import org.json.JSONObject;

import android.app.Activity;
import android.content.Context;
import android.text.TextUtils;
import android.util.Log;

import com.ihighest.app.common.kit.AppKit;
import com.ihighest.app.common.kit.SharedPreferencesKit;
import com.ihighest.app.common.kit.StrKit;
import com.ihighest.app.common.kit.ToastKit;
import com.ihighest.app.infox.Const;
import com.ihighest.app.infox.tools.CheckNetWork;
import com.lidroid.xutils.HttpUtils;
import com.lidroid.xutils.exception.HttpException;
import com.lidroid.xutils.http.RequestParams;
import com.lidroid.xutils.http.RequestParams.HeaderItem;
import com.lidroid.xutils.http.ResponseStream;
import com.lidroid.xutils.http.client.HttpRequest.HttpMethod;

/**
 * Api 请求
 * 
 * @author Vity
 * @date 2015-5-13
 * @mail vity.1215@gmail.com
 */
public class Api {

	static final String TAG = "Api";

	/**
	 * 以post方式请求服务端接口【异步】
	 * 
	 * @param apiUrl
	 *            请求地址
	 * @param param
	 *            参数信息
	 * @param callback
	 *            回调方法
	 * @param context
	 *            当前 context
	 * @author Vity Created at 2015-9-24 下午4:04:59
	 */
	public static void post(String apiUrl, ApiParam param, ApiCallback callback, Context context) {
		request(HttpMethod.POST, Const.API_REQUEST_URL + "/" + apiUrl, param, callback, context);
	}

	/**
	 * 以get方式请求服务端接口【异步】
	 * 
	 * @param apiUrl
	 *            请求地址
	 * @param param
	 *            参数信息
	 * @param callback
	 *            回调方法
	 * @param context
	 *            当前 context
	 * @author Vity Created at 2015-9-24 下午4:04:59
	 */
	public static void get(String apiUrl, ApiParam param, ApiCallback callback, Context context) {
		request(HttpMethod.GET, Const.API_REQUEST_URL + "/" + apiUrl, param, callback, context);
	}

	/**
	 * 获取数据接口内容【异步】
	 * 
	 * @param apiUrl
	 *            数据接口请求地址
	 * @param callback
	 *            回调方法
	 * @param context
	 *            当前context
	 * 
	 * @author Vity Created at 2015-10-9 上午11:50:47
	 */
	public static void data(String apiUrl, ApiCallback callback, Context context) {
		request(HttpMethod.GET, Const.DATA_REQUEST_URL + "/" + apiUrl, null, callback, context);
	}

	/**
	 * 以post方式请求服务端接口【同步】
	 * 
	 * @param apiUrl
	 *            请求地址
	 * @param param
	 *            参数信息
	 * @param context
	 *            当前 context
	 * @author Vity Created at 2015-9-24 下午4:04:59
	 */
	public static <T> T post(String apiUrl, ApiParam param, Context context) {
		return syncRequest(HttpMethod.POST, Const.API_REQUEST_URL + "/" + apiUrl, param, context);
	}

	/**
	 * 以get方式请求服务端接口【同步】
	 * 
	 * @param apiUrl
	 *            请求地址
	 * @param param
	 *            参数信息
	 * @param context
	 *            当前 context
	 * @author Vity Created at 2015-9-24 下午4:04:59
	 */
	public static <T> T get(String apiUrl, ApiParam param, Context context) {
		return syncRequest(HttpMethod.GET, Const.API_REQUEST_URL + "/" + apiUrl, param, context);
	}

	/**
	 * 获取数据接口内容【同步】
	 * 
	 * @param apiUrl
	 *            数据接口请求地址
	 * @param context
	 *            当前context
	 * 
	 * @author Vity Created at 2015-10-9 上午11:50:47
	 */
	public static <T> T data(String apiUrl, Context context) {
		return syncRequest(HttpMethod.GET, Const.DATA_REQUEST_URL + "/" + apiUrl, null, context);
	}

	/**
	 * 同步请求
	 * 
	 * @param method
	 * @param apiUrl
	 * @param param
	 * @param context
	 * 
	 * @author Vity Created at 2015-11-2 上午11:41:02
	 */
	@SuppressWarnings("unchecked")
	static <T> T syncRequest(HttpMethod method, String apiUrl, ApiParam param, Context context) {
		if (!CheckNetWork.isConnected(context)) {
			// ToastKit.showShort(context, "网络不可用");
		}
		Log.d(TAG, "Url : " + apiUrl + " ; Method : " + method.name());
		HttpUtils utils = new HttpUtils(10 * 1000);
		utils.configCurrentHttpCacheExpiry(10 * 1000);
		try {
			ResponseStream rs = utils.sendSync(method, apiUrl, wrapParams(method, param, context));
			int status = rs.getStatusCode();
			String resp = isToString(rs.getBaseStream(), "UTF-8");
			Log.d(TAG, "Result:" + status + " >> " + resp);
			if (status == 200 && !TextUtils.isEmpty(resp)) {
				resp = resp.trim();
				if (resp.startsWith("{")) {
					return (T) new JSONObject(resp);
				} else if (resp.startsWith("[")) {
					return (T) new JSONArray(resp);
				}
			}
		} catch (HttpException e) {
			// Token失效处理
			if (e.getExceptionCode() == 403) {
				AppKit.cleanUserInfo(context);
			} else if (e.getExceptionCode() == 500) {
				if (context instanceof Activity) {
					ToastKit.showShort(context, "服务器繁忙，请稍后再试");
				} else {
					ToastKit.showShort(context, "服务器繁忙，请稍后再试");
				}
			} else if (e.getExceptionCode() == 401) {
				if (context instanceof Activity) {
					ToastKit.showShort(context, "请求失败");
				} else {
					ToastKit.showShort(context, "请求失败");
				}
			} else if (e.getExceptionCode() == 400) {
				if (context instanceof Activity) {
					ToastKit.showShort(context, "请求失败");
				} else {
					ToastKit.showShort(context, "请求失败");
				}
			} else if (e.getExceptionCode() == 504) {
				if (context instanceof Activity) {
					ToastKit.showShort(context, "服务器响应超时");
				} else {
					ToastKit.showShort(context, "服务器响应超时");
				}
			} else if (e.getExceptionCode() == 404) {
			}
			Log.e(TAG, "HTTP Code: " + e.getExceptionCode() + "  MSG: " + e.getMessage(), e);
		} catch (Exception e) {
			Log.e(TAG, e.getMessage(), e);
		}
		return null;
	}

	/**
	 * 将InputStream转换成某种字符编码的String
	 * 
	 * @param in
	 * @param encoding
	 * @return
	 * @throws Exception
	 */
	static String isToString(InputStream in, String encoding) throws Exception {

		ByteArrayOutputStream outStream = new ByteArrayOutputStream();
		byte[] data = new byte[4096];
		int count = -1;
		while ((count = in.read(data, 0, 4096)) != -1)
			outStream.write(data, 0, count);

		data = null;
		return new String(outStream.toByteArray(), encoding);
	}

	/**
	 * 异步请求
	 * 
	 * @param method
	 * @param apiUrl
	 * @param param
	 * @param callback
	 * @param context
	 * 
	 * @author Vity Created at 2015-11-2 上午11:40:43
	 */

	static void request(HttpMethod method, String apiUrl, ApiParam param, ApiCallback callback, Context context) {
		if (!CheckNetWork.isConnected(context)) {
			// ToastKit.showShort(context, "网络不可用");
		}
		Log.d(TAG, "Url : " + apiUrl + " ; Method : " + method.name());
		HttpUtils utils = new HttpUtils(10 * 1000);
		utils.configCurrentHttpCacheExpiry(10 * 1000);
		utils.send(method, apiUrl, wrapParams(method, param, context), callback);
	}

	/**
	 * 组合参数
	 * 
	 * @param method
	 * @param param
	 * @param context
	 * @return
	 * 
	 * @author Vity Created at 2015-11-2 上午11:43:35
	 */
	@SuppressWarnings({ "deprecation", "unchecked" })
	static RequestParams wrapParams(HttpMethod method, ApiParam param, Context context) {
		String token = SharedPreferencesKit.getString(context, Const.SP_KEY_USER_TOKEN);
		token = StrKit.isBlank(token) ? "guest" : token;
		String area = null;
		try {
			if (SharedPreferencesKit.getJsonObject(context, Const.SP_KEY_BD_LOCAITON) != null) {
				area = SharedPreferencesKit.getJsonObject(context, Const.SP_KEY_BD_LOCAITON).getString("cityCode");
			}
		} catch (Exception ex) {
		}
		area = TextUtils.isEmpty(area) || "null".equalsIgnoreCase(area) ? "empty" : area;
		String nonce = String.valueOf(System.nanoTime());
		String time = String.valueOf(System.currentTimeMillis());
		String client = AppKit.getPhoneModel() + "," + AppKit.getAndroidVersion();
		String sign = AppKit.md5(token + area + nonce + client + time);
		RequestParams rp = new RequestParams();
		rp.setHeader("Token", token);
		rp.setHeader("Area", area);
		rp.setHeader("Nonce", nonce);
		rp.setHeader("Client", client);
		rp.setHeader("Time", time);
		rp.setHeader("Sign", sign);
		rp.setHeader("HT-Channel", AppKit.getChannel(context));
		for (HeaderItem hi : rp.getHeaders()) {
			Log.d(TAG, "Header : " + hi.header.getName() + " --> " + hi.header.getValue());
		}
		if (param != null && param.getParams().size() > 0) {
			try {
				Object value;
				for (String key : param.getParams().keySet()) {
					value = param.getParams().get(key);
					Log.d(TAG, "Param : " + key + " --> " + value);
					if (method == HttpMethod.POST) {
						if (value instanceof File) {
							rp.addBodyParameter(key, (File) value);
						} else if (value instanceof ArrayList) {
							ArrayList<File> list = (ArrayList<File>) value;
							if (list != null && !list.isEmpty()) {
								for (int i = 0; i < list.size(); i++) {
									rp.addBodyParameter(key + "_" + i, list.get(i));
								}
							}
						} else {
							rp.addBodyParameter(key, (String) value);
						}
					} else if (method == HttpMethod.GET) {
						rp.addQueryStringParameter(key, (String) value);
					}
				}
			} catch (Exception e) {
				Log.e(TAG, e.getMessage(), e);
			}
		}
		return rp;
	}
}
